﻿using System;
using System.Threading;
using System.Text;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Dispatcher;
using System.Xml;
using System.IO;
using nwrole.toolbox.OneWaySoapChannelLib.Channel;
using nwrole.toolbox.sync.entity;

namespace OneWaySoapChannelLib.Channel
{
    internal class OneWaySoapOutputChannel : ChannelBase, IOutputChannel
    {

        SyncEntityRepository _repository = null;
        MessageDispatcher _dispatcher = null;
        EndpointAddress _remoteAddress;
        Uri _via;
        string _connectionString;

        public SyncEntityRepository repository
        {
            get
            {
                if (_repository == null)
                {
                    _repository = new SyncEntityRepository(_connectionString, _connectionString);
                }
                return _repository;
            }
        }

        public MessageDispatcher dispatcher
        {
            get
            {
                if (_dispatcher == null)
                {
                    _dispatcher = new MessageDispatcher(repository);
                }
                return _dispatcher;
            }
        }

        public OneWaySoapOutputChannel(ChannelManagerBase factory, EndpointAddress remoteAddress, Uri via, string connectionString)
            : base(factory)
        {
            this._remoteAddress = remoteAddress;
            this._via = via;
            this._connectionString = connectionString;
        }

        public IAsyncResult BeginSend(Message message, TimeSpan timeout, AsyncCallback callback, object state)
        {
            this.Send(message, timeout);
            return new CompletedAsyncResult(callback, state);
        }

        public IAsyncResult BeginSend(Message message, AsyncCallback callback, object state)
        {
            return BeginSend(message, base.DefaultSendTimeout, callback, state);
        }

        public void EndSend(IAsyncResult result)
        {
            CompletedAsyncResult.End(result);
        }

        public void Send(Message message)
        {
            Send(message, base.DefaultSendTimeout);
        }

        public void Send(Message message, TimeSpan timeout)
        {
            try
            {
                base.ThrowIfDisposedOrNotOpen();
                RemoteAddress.ApplyTo(message);

                MessageVersion ver = message.Version;
                MemoryStream ms = new MemoryStream();
                StringWriter sw = new StringWriter();

                XmlWriterSettings settings = new XmlWriterSettings();
                settings.OmitXmlDeclaration = true;

                XmlWriter w = XmlWriter.Create(sw, settings);

                message.WriteMessage(w);
                w.Flush();

                SyncMessage msg = new SyncMessage();
                msg.MessageStatus = MessageStatusEnum.New;
                msg.SoapBody = sw.ToString();
                msg.LockDateTime = DateTime.Now.AddMinutes(10);
                // // // repository.Insert(msg);
                // System.IO.File.WriteAllText(@"c:\log\message.soap", sw.ToString());

                ThreadPool.QueueUserWorkItem(new WaitCallback(this.SendMessage), msg);
            }
            catch (Exception e)
            {
                throw new Exception("Error in send message", e);
            }

        }

        protected void SendMessage(object state)
        {
            try
            {
                dispatcher.Send(state as SyncMessage);
            }
            catch (Exception)
            {
                // handle error
            }
        }

        public EndpointAddress RemoteAddress
        {
            get { return _remoteAddress; }
        }

        public Uri Via
        {
            get { return _via; }
        }

        public override T GetProperty<T>()
        {
            if (typeof(T) == typeof(FaultConverter))
            {
                return FaultConverter.GetDefaultFaultConverter(MessageVersion.Soap12WSAddressing10) as T;
            }
            return base.GetProperty<T>();
        }

        protected override void OnAbort()
        {
            throw new NotImplementedException();
        }

        protected override IAsyncResult OnBeginClose(TimeSpan timeout, AsyncCallback callback, object state)
        {
            throw new NotImplementedException();
        }

        protected override IAsyncResult OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state)
        {
            throw new NotImplementedException();
        }

        protected override void OnClose(TimeSpan timeout)
        {
            throw new NotImplementedException();
        }

        protected override void OnEndClose(IAsyncResult result)
        {
            throw new NotImplementedException();
        }

        protected override void OnEndOpen(IAsyncResult result)
        {
            throw new NotImplementedException();
        }

        protected override void OnOpen(TimeSpan timeout)
        {
        }
    }
}
